package main

import "fmt"

/**
1、切片：slice
	1）slice代表变长的序列，序列中每个元素都有相同的类型。
	2）slice的语法与数组很像，只是没有固定长度而已。
	3）一个slice由三个部分构成：指针、长度、容量。
		3.1）指针指向第一个元素并不一定就是数组的第一个元素。
		3.2）长度对应slice中元素的数目，长度不能超过容量。

2、包含 make函数的使用
	1）make函数创建一个指定元素类型、长度和容量的slice。（容量部分可以省略，这时容量将等于长度）
		第一种：make([]T, len)
		第二种：make([]T, len, cap)
	2）在底层，make创建了一个匿名的数组变量，然后返回一个slice；

3、结构体字面值

4、append函数


*/

func main() {
	// 构造一个一年12个月的数组
	months := []string{0: "", 1: "January--1月份", 2: "February--2月份", 3: "March--3月份", 4: "April--4月份", 5: "May--5月份", 6: "June--6月份",
		7: "July--7月份", 8: "August--8月份", 9: "September", 10: "October", 11: "November", 12: "December"}
	fmt.Println("第一个月：", months[1])

	// 使用slice构造一年的第2季度
	Q2 := months[4:7]
	fmt.Println("一年的第2季度是：", Q2)

	// 夏天
	summer := months[6:9]
	fmt.Println("暑假的月份是：", summer)

	// 比较Q2与夏天中重叠的月份
	for _, value1 := range Q2 {
		for _, value2 := range summer {
			if value1 == value2 {
				fmt.Println("相同的月份是：", value1)
			}
		}
	}

	// slice 切片中的长度和容量
	// 对于长度和容量的理解是，上面这个summer是来自数组months的一个切片，summer中的元素有三个，所以长度是3
	// summer切片本身是来自months的，所以的summer的容量是根据需要变化的，但是最大不能超过months的长度13
	// 对切片的操作超出cap(summer)的上限，将导致一个panic的异常
	//fmt.Println(summer[:15])

	a := [...]int{0, 1, 2, 3, 4, 5, 6}
	reverse(a[:])
	fmt.Println("反转后的数组：", a)

	s := []int{0, 1, 2, 3, 4, 5, 6}
	reverse(s[:2])
	fmt.Println(s)
	reverse(s[2:])
	fmt.Println(s)
	reverse(s)
	fmt.Println(s)

	// slice中唯一合法的比较操作是和 nil 比较
	// 1、一个零值的slice等于nil，一个nil值的slice没有底层数组，一个nil值的slice的长度和容量都是0
	// 2、也有非nil值的slice的长度和容量也是0的，如：[]int{} 或者 make([]int, 3)[3:]
	// 3、判断一个slice是否为空，使用len(s) == 0 来判断。
	if summer == nil {
		fmt.Println("slice中唯一合法的比较操作是和 nil 比较")
	}

	var runes []rune
	for _, r := range "Hello,世界" {
		runes = append(runes, r)
	}
	fmt.Printf("%q\n", runes)

	// 每次容量的变化都会导致重新分配内存和copy操作
	var x, y []int
	for i := 0; i < 10; i++ {
		y = appendInt(x, i)
		fmt.Printf("%d cap=%d\t%v\n", i, cap(y), y)
		x = y
	}

	var z []int
	z = append(z, 1)
	z = append(z, 2, 3)
	z = append(z, 4, 5, 6)
	// 这里的...省略号表示可以接收变长的参数为slice
	z = append(z, z...)
	fmt.Println(z)

}

// 反转
func reverse(s []int) {
	for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
		s[i], s[j] = s[j], s[i]
	}
}

// 第一版本的appendInt函数
func appendInt(x []int, y int) []int {
	var z []int
	zlen := len(x) + 1
	if zlen <= cap(x) {
		// There is room to grow.  Extend the slice.
		z = x[:zlen]
	} else {
		// There is insufficient space.  Allocate a new array.
		// Grow by doubling, for amortized linear complexity.
		zcap := zlen
		if zcap < 2*len(x) {
			zcap = 2 * len(x)
		}
		z = make([]int, zlen, zcap)
		copy(z, x) // a built-in function; see text
	}
	z[len(x)] = y
	return z
}
